package route2

import (
	"fmt"
	"gitee.com/chejiangyi/bsfgo/core/utils"
	controller2 "gitee.com/chejiangyi/bsfgo/gin2/controller"
	"github.com/gin-gonic/gin"
	"reflect"
	"strings"
)

var RouteUtil = &RouteUtilTool{}
var validMethods = map[string]bool{
	"GET":     true,
	"POST":    true,
	"PUT":     true,
	"DELETE":  true,
	"PATCH":   true,
	"HEAD":    true,
	"OPTIONS": true,
}

type RouteInfo struct {
	Path   string // 路由路径
	Method string // HTTP方法(GET/POST等)
}

type RouteUtilTool struct {
}

func (r *RouteUtilTool) AutoRegisterRoutes(httpMethods []string, router *gin.RouterGroup, controller interface{}) {
	ctrlType := reflect.TypeOf(controller)
	ctrlValue := reflect.ValueOf(controller)
	controllerName := utils.StringUtil.FirstLetterToLower(strings.ReplaceAll(utils.ReflectUtil.GetTypeName(controller), "Controller", ""))
	//跳过基类
	skipMethods := utils.ReflectUtil.GetMethodsMap((*controller2.BaseWebController)(nil))
	// 遍历控制器方法
	for i := 0; i < ctrlType.NumMethod(); i++ {
		method := ctrlType.Method(i)
		// 跳过非公开方法或不符合条件的方法
		if !method.IsExported() {
			continue
		}
		//baseWebController嵌入方法跳过
		if _, ok := skipMethods[method.Name]; ok {
			continue
		}
		//参数为*gin.Context
		if !(method.Type.NumIn() == 2 && method.Type.In(1) == reflect.TypeOf((*gin.Context)(nil))) {
			continue
		}
		path := fmt.Sprintf("/%v/%v", controllerName, utils.StringUtil.FirstLetterToLower(method.Name))
		registerRoute(router, httpMethods, path, ctrlValue.Method(i))
	}
}

// 注册路由到Gin
func registerRoute(router *gin.RouterGroup, methods []string, path string, handler reflect.Value) {
	var routeMethods []string
	for _, method := range methods {
		switch strings.ToUpper(method) {
		case "GET":
			router.GET(path, createHandlerFunc(handler))
			routeMethods = append(routeMethods, method)
		case "POST":
			router.POST(path, createHandlerFunc(handler))
			routeMethods = append(routeMethods, method)
		case "PUT":
			router.PUT(path, createHandlerFunc(handler))
			routeMethods = append(routeMethods, method)
		case "DELETE":
			router.DELETE(path, createHandlerFunc(handler))
			routeMethods = append(routeMethods, method)
		case "PATCH":
			router.PATCH(path, createHandlerFunc(handler))
			routeMethods = append(routeMethods, method)
		case "HEAD":
			router.HEAD(path, createHandlerFunc(handler))
			routeMethods = append(routeMethods, method)
		case "OPTIONS":
			router.OPTIONS(path, createHandlerFunc(handler))
			routeMethods = append(routeMethods, method)
		}
	}
	logInfo(router, routeMethods, path)
}

func logInfo(router *gin.RouterGroup, method []string, path string) {
	utils.LogUtil.Info("自动路由注册:%v %v", method, router.BasePath()+path)
}

func createHandlerFunc(handler reflect.Value) gin.HandlerFunc {
	return func(c *gin.Context) {
		// 调用控制器方法,会有少许性能损失
		handler.Call([]reflect.Value{reflect.ValueOf(c)})
	}
}
